package com.frank.oj.manager;

import cn.hutool.core.lang.Validator;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.system.oshi.OshiUtil;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException;
import com.frank.oj.common.exception.StatusFailException;
import com.frank.oj.config.NacosSwitchConfig;
import com.frank.oj.model.dto.TestEmailDTO;
import com.frank.oj.model.vo.ConfigVO;
import com.frank.oj.service.entity.common.FileEntityService;
import com.frank.oj.service.entity.judge.RemoteJudgeAccountEntityService;
import com.frank.oj.utils.ConfigUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

/**
 * @author frank
 * @Date 2024/3/27
 */
@Component
@Slf4j(topic = "hcoj")
public class ConfigManager {
    @Resource
    private ConfigVO configVo;

    @Resource
    private EmailManager emailManager;

    @Resource
    private FileEntityService fileEntityService;

    @Resource
    private RemoteJudgeAccountEntityService remoteJudgeAccountEntityService;

    @Resource
    private ConfigUtils configUtils;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private DiscoveryClient discoveryClient;

    @Resource
    private NacosSwitchConfig nacosSwitchConfig;

    @Value("${service-url.name}")
    private String judgeServiceName;

    @Value("${spring.application.name}")
    private String currentServiceName;

    @Value("${spring.cloud.nacos.url}")
    private String NACOS_URL;

    @Value("${spring.cloud.nacos.config.prefix}")
    private String prefix;

    @Value("${spring.profiles.active}")
    private String active;

    @Value("${spring.cloud.nacos.config.file-extension}")
    private String fileExtension;

    @Value("${spring.cloud.nacos.config.group}")
    private String GROUP;

    @Value("${spring.cloud.nacos.config.type}")
    private String TYPE;

    @Value("${spring.cloud.nacos.config.username}")
    private String nacosUsername;

    @Value("${spring.cloud.nacos.config.password}")
    private String nacosPassword;


    public JSONObject getServiceInfo() {

        JSONObject result = new JSONObject();

        // 在nacos中获取当前服务信息
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances(currentServiceName);

        // 获取nacos中心配置所在的机器环境
        String response = restTemplate.getForObject(NACOS_URL + "/nacos/v1/ns/operator/metrics", String.class);

        JSONObject jsonObject = JSONUtil.parseObj(response);
        // 获取当前数据后台所在机器环境
        // 内存
        double totalMemory = OshiUtil.getMemory().getTotal();
        double freeMemory = OshiUtil.getMemory().getAvailable();
        double value=freeMemory/totalMemory;
        String percentMemoryLoad = String.format("%.2f", (1 - value) * 100) + "%"; // 当前服务所在机器内存使用率

        // cpu
        Integer cpuNum = OshiUtil.getCpuInfo().getCpuNum();
        double cpuUsed = 100 - OshiUtil.getCpuInfo().getFree();
        String percentCpuLoad = String.format("%.2f", cpuUsed) + "%";

        HashMap<String, Object> map = new HashMap<>();
        map.put("nacos", jsonObject);
        map.put("backupCores", cpuNum);
        map.put("backupService", serviceInstances);
        map.put("backupPercentCpuLoad", percentCpuLoad);
        map.put("backupPercentMemoryLoad", percentMemoryLoad);

        result.putAll(map);
        return result;
    }

    public List<JSONObject> getJudgeServerInfo(){
        LinkedList<JSONObject> serviceInfoList = new LinkedList<>();
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances(judgeServiceName);

        for (ServiceInstance serviceInstance : serviceInstances) {
            try {
                String result = restTemplate.getForObject(serviceInstance.getUri() + "/get-sys-config", String.class);
                JSONObject jsonObject = JSONUtil.parseObj(result, false);
                jsonObject.putOnce("service",serviceInstance);
                serviceInfoList.add(jsonObject);
            } catch (Exception e) {
                log.error("[Admin Dashboard] get judge service info error, uri={}, error={}", serviceInstance.getUri(),e.getMessage());
            }
        }
        return serviceInfoList;
    }

    public boolean sendNewConfigToNacos() {

        Properties properties = new Properties();
        properties.put("serverAddr", NACOS_URL);
        properties.put("username", nacosUsername);
        properties.put("password", nacosPassword);

        com.alibaba.nacos.api.config.ConfigService configService = null;
        try {
            configService = NacosFactory.createConfigService(properties);
            return configService.publishConfig(prefix + "-" + active + "." + fileExtension, GROUP, configUtils.getConfigContent(), TYPE);
        } catch (NacosException e) {
            log.error("HC：网站配置修改异常--------->{}", e.getMessage());
        }
        return false;
    }

    public void testEmail(TestEmailDTO testEmailDto) throws StatusFailException {
        String email = testEmailDto.getEmail();
        if (StringUtils.isEmpty(email)) {
            throw new StatusFailException("测试的邮箱不能为空！");
        }
        boolean isEmail = Validator.isEmail(email);
        if (isEmail) {
            emailManager.testEmail(email);
        } else {
            throw new StatusFailException("测试的邮箱格式不正确！");
        }
    }
}
